#include "tb_rpc.h"
#include "esp_log.h"
#include "cJSON.h"
#include "mqtt_client.h"
#include <string.h>

#define RPC_TOPIC_PREFIX "v1/devices/me/rpc/request/"
#define RPC_RESPONSE_PREFIX "v1/devices/me/rpc/response/"
#define RPC_REQUEST_PREFIX "v1/devices/me/rpc/request/+"

#define MAX_RPC_METHODS 100
#define TAG "TB_RPC"

static tb_rpc_method_t rpc_methods[MAX_RPC_METHODS];
static int rpc_method_count = 0;
static esp_mqtt_client_handle_t tb_client = NULL;

void tb_rpc_init(esp_mqtt_client_handle_t client) {
    tb_client = client;
    esp_mqtt_client_subscribe(client,RPC_REQUEST_PREFIX,1);
}

void tb_rpc_subscribe(const char* method, tb_rpc_callback_t handler) {
    if (rpc_method_count < MAX_RPC_METHODS) {
        rpc_methods[rpc_method_count].method = method;
        rpc_methods[rpc_method_count].handler = handler;
        rpc_method_count++;
    }
}

static const char* find_and_invoke_handler(const char* method, cJSON* params) {
    for (int i = 0; i < rpc_method_count; i++) {
        if (strcmp(method, rpc_methods[i].method) == 0) {
            return rpc_methods[i].handler(params);
        }
    }
    return "{\"error\":\"method_not_found\"}";
}

void tb_handle_rpc(const char* topic, const uint8_t* payload, int length) {
    if (!topic || !payload) return;

    // 判断是否是 RPC 请求主题
    if (strncmp(topic, RPC_TOPIC_PREFIX, strlen(RPC_TOPIC_PREFIX)) != 0) return;

    const char* request_id = topic + strlen(RPC_TOPIC_PREFIX);  // 提取请求ID

    // 解析 JSON payload
    char json_copy[256] = {0};
    memcpy(json_copy, payload, length < sizeof(json_copy) ? length : sizeof(json_copy) - 1);

    cJSON* root = cJSON_Parse(json_copy);
    if (!root) {
        ESP_LOGW(TAG, "Invalid JSON in RPC payload");
        return;
    }

    const char* method = cJSON_GetObjectItem(root, "method")->valuestring;
    cJSON* params = cJSON_GetObjectItem(root, "params");

    const char* result = find_and_invoke_handler(method, params);

    // 构造响应 topic 并发布
    char response_topic[128];
    snprintf(response_topic, sizeof(response_topic), "%s%s", RPC_RESPONSE_PREFIX, request_id);

    esp_mqtt_client_publish(tb_client, response_topic, result, 0, 1, 0);

    ESP_LOGI(TAG, "RPC [%s] handled, response sent: %s", method, result);
    cJSON_Delete(root);
}
